// package macaddr 解析和反解析MAC地址，下一个MAC地址……
package macaddr

import (
	"math/rand"
	"net"
	"time"
)

var (
	Zero  = MAC{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
	Bcast = MAC{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
)

// MAC 包装标准库的 net.HardwareAddr 类型
// 只支持 IEEE 802 MAC-48
type MAC net.HardwareAddr

// New 包装 net.HardwareAddr
func New(hw net.HardwareAddr) MAC {
	if hw == nil || len(hw) != 6 {
		return nil
	}
	return MAC(hw)
}

// NewRandMAC 创建一个随机 MAC 地址
func NewRandMAC(oui [3]byte) MAC {
	rand.Seed(time.Now().UnixNano())
	return MAC{
		oui[0], oui[1], oui[2],
		byte(rand.Intn(0xff)), byte(rand.Intn(0xff)), byte(rand.Intn(0xff)),
	}
}

// NewFromMCastIP4 根据组播 IPv4 创建一个开头为 0x01005e 的组播地址
func NewFromMCastIP4(ip4 net.IP) MAC {
	ip4 = ip4.To4()
	if ip4.IsMulticast() {
		return MAC{0x1, 0x0, 0x5e, ip4[1] & 0b01111111, ip4[2], ip4[3]}
	}
	return nil
}

// NewFromMCastIP6 根据组播 IPv4 创建一个开头为 0x3333 的组播地址
func NewFromMCastIP6(ip6 net.IP) MAC {
	if len(ip6) != net.IPv6len || !ip6.IsMulticast() {
		return nil
	}
	return MAC{0x33, 0x33, ip6[net.IPv6len-4], ip6[net.IPv6len-3], ip6[net.IPv6len-2], ip6[net.IPv6len-1]}
}

// HardwareAddr 返回标准库的类型
func (m MAC) HardwareAddr() net.HardwareAddr {
	return net.HardwareAddr(m)
}

// Next 返回下一个地址
func (m MAC) Next() MAC {
	if m == nil || len(m) != 6 {
		m = Zero
	}

	newMAC := make(MAC, 6)
	copy(newMAC, m)

	for i := len(m) - 1; i >= 0; i-- {
		if newMAC[i] == 0xff {
			newMAC[i] = 0
			continue
		}

		newMAC[i]++
		return newMAC
	}

	return Zero
}

// IsMulticast 第一位是 0x01 则返回 true
func (m MAC) IsMulticast() bool {
	if m == nil || len(m) != 6 {
		return false
	}

	return m[0] == 0x01 || (m[0] == 0x33 && m[1] == 0x33)
}
